import {
    Injectable,
    Logger,
    HttpException,
    HttpStatus,
    Inject,
} from '@nestjs/common';
import {Like, Repository} from 'typeorm';
import {InjectRepository} from '@nestjs/typeorm';
import {RegisterUserDto} from './dto/register-user.dto';
import {LoginUserDto} from './dto/login-user.dto';
import {User} from './entities/user.entity';
import {Role} from './entities/role.entity';
import {Permission} from './entities/permission.entity';
import {RedisService} from 'src/middleware/redis/redis.service';
import {md5} from '../utils/md5';
import {LoginUserVo} from './vo/login-user.vo';
import {UpdateUserPasswordDto} from './dto/update-user-password.dto';
import {UpdateUserDto} from './dto/udpate-user.dto';
import {UserListVo} from './vo/user-list.vo';
import {DisabledUserDto} from "./dto/disabled-user.dto";

@Injectable()
export class UserService {
    @Inject(RedisService)
    private redisService: RedisService;
    private logger = new Logger();

    @InjectRepository(User)
    private userRepository: Repository<User>;
    @InjectRepository(Role)
    private roleRepository: Repository<Role>;
    @InjectRepository(Permission)
    private permissionRepository: Repository<Permission>;

    // 注册
    async register(user: RegisterUserDto) {
        const captcha = await this.redisService.get(`captcha_${user.email}`);
        if (!captcha) {
            throw new HttpException('验证码已失效', HttpStatus.BAD_REQUEST);
        }

        if (user.captcha !== captcha) {
            throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST);
        }

        const foundUser = await this.userRepository.findOneBy({
            username: user.username,
        });

        if (foundUser) {
            throw new HttpException('用户已存在', HttpStatus.BAD_REQUEST);
        }

        const newUser = new User();
        newUser.username = user.username;
        newUser.password = md5('888888');
        newUser.phoneNumber = user.phoneNumber;
        newUser.email = user.email;
        newUser.nickName = '会议室小生';
        newUser.headPic = 'http://localhost:9000/dev/err.png'
        newUser.isAdmin = false;

        try {
            await this.userRepository.save(newUser);
            return '注册成功';
        } catch (e) {
            this.logger.error(e, UserService);
            return '注册失败';
        }
    }

    // 插入数据
    async initData() {
        const user1 = new User();
        user1.username = 'zhangsan';
        user1.password = md5('111111');
        user1.email = 'xxx@xx.com';
        user1.isAdmin = true;
        user1.nickName = '张三';
        user1.phoneNumber = '13233323333';

        const user2 = new User();
        user2.username = 'lisi';
        user2.password = md5('222222');
        user2.email = 'yy@yy.com';
        user2.nickName = '李四';

        const role1 = new Role();
        role1.name = '管理员';

        const role2 = new Role();
        role2.name = '普通用户';

        const permission1 = new Permission();
        permission1.code = 'ccc';
        permission1.description = '访问 ccc 接口';

        const permission2 = new Permission();
        permission2.code = 'ddd';
        permission2.description = '访问 ddd 接口';

        user1.roles = [role1];
        user2.roles = [role2];

        role1.permissions = [permission1, permission2];
        role2.permissions = [permission1];

        await this.permissionRepository.save([permission1, permission2]);
        await this.roleRepository.save([role1, role2]);
        await this.userRepository.save([user1, user2]);
    }

    // 登录
    async login(loginUserDto: LoginUserDto, isAdmin: boolean) {
        // 验证图片验证码
        const captcha = await this.redisService.get(
            `svg_captcha_${loginUserDto.captcha}`,
        );
        if (!captcha) {
            throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
        }
        console.log(isAdmin, 'isAdmin');

        const user = await this.userRepository.findOne({
            where: {
                username: loginUserDto.username,
                isAdmin: isAdmin,
            },
            relations: ['roles', 'roles.permissions'],
        });

        if (!user) {
            throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
        }
        if (user.isFrozen) {
            throw new HttpException('用户已冻结', HttpStatus.BAD_REQUEST);
        }

        if (user.password !== md5(loginUserDto.password)) {
            throw new HttpException('密码错误', HttpStatus.BAD_REQUEST);
        }

        const vo = new LoginUserVo();
        vo.userInfo = {
            id: user.id,
            username: user.username,
            nickName: user.nickName,
            email: user.email,
            phoneNumber: user.phoneNumber,
            headPic: user.headPic,
            createTime: user.createTime.getTime(),
            isFrozen: user.isFrozen,
            isAdmin: user.isAdmin,
            roles: user.roles.map((item) => item.name),
            permissions: user.roles.reduce((arr, item) => {
                item.permissions.forEach((permission) => {
                    if (arr.indexOf(permission) === -1) {
                        arr.push(permission);
                    }
                });
                return arr;
            }, []),
        };

        await this.redisService.delete(`svg_captcha_${loginUserDto.captcha}`);
        return vo;
    }

    //刷新token
    async findUserById(userId: number, isAdmin: boolean) {
        const user = await this.userRepository.findOne({
            where: {
                id: userId,
                isAdmin,
            },
            relations: ['roles', 'roles.permissions'],
        });

        return {
            id: user.id,
            username: user.username,
            isAdmin: user.isAdmin,
            email: user.email,
            roles: user.roles.map((item) => item.name),
            permissions: user.roles.reduce((arr, item) => {
                item.permissions.forEach((permission) => {
                    if (arr.indexOf(permission) === -1) {
                        arr.push(permission);
                    }
                });
                return arr;
            }, []),
        };
    }

    // 个人信息
    async findUserDetailById(userId: number) {
        const user = await this.userRepository.findOne({
            where: {
                id: userId,
            },
        });

        return user;
    }

    // 用户列表详情
    async findUserListById(id: number) {
        const user = await this.userRepository.findOne({
            where: {
                id: id,
            },
        });

        return user;
    }


    // 修改用户端、管理端密码
    async updatePassword(passwordDto: UpdateUserPasswordDto, isAdmin: boolean) {
        const user = await this.userRepository.findOne({
            where: {
                username: passwordDto.username,
                isAdmin: !isAdmin,
            },
            relations: ['roles', 'roles.permissions'],
        });

        if (!user) {
            throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
        }
        const captcha = await this.redisService.get(
            `update_password_captcha_${passwordDto.email}`,
        );

        if (!captcha) {
            throw new HttpException('验证码已失效', HttpStatus.BAD_REQUEST);
        }

        if (passwordDto.captcha !== captcha) {
            throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST);
        }

        const foundUser = await this.userRepository.findOneBy({
            username: passwordDto.username,
        });

        if (foundUser.email !== passwordDto.email) {
            throw new HttpException('邮箱不正确', HttpStatus.BAD_REQUEST);
        }

        foundUser.password = md5(passwordDto.password);

        try {
            await this.userRepository.save(foundUser);
            return '密码修改成功';
        } catch (e) {
            this.logger.error(e, UserService);
            return '密码修改失败';
        }
    }

    // 修改用户端、管理端信息
    async update(userId: number, updateUserDto: UpdateUserDto) {
        const captcha = await this.redisService.get(
            `update_user_captcha_${updateUserDto.email}`,
        );

        if (!captcha) {
            throw new HttpException('验证码已失效', HttpStatus.BAD_REQUEST);
        }

        if (updateUserDto.captcha !== captcha) {
            throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST);
        }

        const foundUser = await this.userRepository.findOneBy({
            id: userId,
        });

        if (updateUserDto.nickName) {
            foundUser.nickName = updateUserDto.nickName;
        }
        if (updateUserDto.headPic) {
            foundUser.headPic = updateUserDto.headPic;
        }

        if (updateUserDto.username) {
            foundUser.username = updateUserDto.username;
        }

        if (updateUserDto.phoneNumber) {
            foundUser.phoneNumber = updateUserDto.phoneNumber;
        }

        try {
            await this.userRepository.save(foundUser);
            return '用户信息修改成功';
        } catch (e) {
            this.logger.error(e, UserService);
            return '用户信息修改成功';
        }
    }

    // 冻结用户
    async freezeUserById(id: number) {
        const user = await this.userRepository.findOneBy({
            id,
        });

        user.isFrozen = true;

        await this.userRepository.save(user);
    }

    async disabledUse(disabled: DisabledUserDto) {
        const user = await this.userRepository.findOneBy({
            id: Number(disabled.id)
        })
        user.isFrozen = disabled.status
        await this.userRepository.save(user)
    }

    // 列表
    async findUsers(
        username: string,
        nickName: string,
        email: string,
        pageNum: number,
        pageSize: number,
    ) {
        const skipCount = (pageNum - 1) * pageSize;

        const condition: Record<string, any> = {};

        if (username) {
            condition.username = Like(`%${username}%`);
        }
        if (nickName) {
            condition.nickName = Like(`%${nickName}%`);
        }
        if (email) {
            condition.email = Like(`%${email}%`);
        }

        const [users, total] = await this.userRepository.findAndCount({
            select: [
                'id',
                'username',
                'nickName',
                'email',
                'phoneNumber',
                'isAdmin',
                'isFrozen',
                'headPic',
                'createTime',
            ],
            skip: skipCount,
            take: pageSize,
            where: condition,
        });

        const vo = new UserListVo();

        vo.list = users;
        vo.pageNum = pageNum;
        vo.pageSize = pageSize;
        vo.total = total;
        return vo;
    }
}
